package cn.yitun.chat.yitunservermanagecore.general.manage.index.service.impl;

import cn.yitun.chat.yituncommonmessage.ExceptionEnum;
import cn.yitun.chat.yituncommonmessage.YitunException;
import cn.yitun.chat.yituncommonmessage.result.ResultMessage;
import cn.yitun.chat.yituncommonutil.YitunMD5Util;
import cn.yitun.chat.yituncommonutil.YitunStringUtil;
import cn.yitun.chat.yituncommonweb.util.YitunHttpUtil;
import cn.yitun.chat.yitunservercommonlib.basebean.web.JwtUserDto;
import cn.yitun.chat.yitunservercommonlib.converter.dto2po.user.UserDto2PoConverter;
import cn.yitun.chat.yitunservercommonlib.crud.yitun.BaseInfo;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.login.OnlineUserDto;
import cn.yitun.chat.yitunservercommonlib.dataentity.po.login.LoginLogPo;
import cn.yitun.chat.yitunservercommonlib.dataentity.po.system.user.UserInfo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.system.MenuVo;
import cn.yitun.chat.yitunservercommonlib.enums.login.LoginStatusEnums;
import cn.yitun.chat.yitunservercommonlib.enums.login.LoginTypeEnums;
import cn.yitun.chat.yitunservercommonlib.enums.system.UserRoleTypeEnums;
import cn.yitun.chat.yitunservercommonlib.util.cache.TokenTemporaryCache;
import cn.yitun.chat.yitunservercommonmessage.data.user.LoginDto;
import cn.yitun.chat.yitunserverimbase.dao.login.LoginLogDao;
import cn.yitun.chat.yitunserverimbase.dao.login.UserJwtDao;
import cn.yitun.chat.yitunserverimbase.dao.system.MenuDao;
import cn.yitun.chat.yitunserverimbase.dao.system.UserDao;
import cn.yitun.chat.yitunservermanagecore.general.bridge.auth.manager.AuthManager;
import cn.yitun.chat.yitunservermanagecore.general.manage.index.service.IndexService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * date 2018-06-13 10:27:23<br>
 * description
 * 
 * @author yitun<br>
 * @since
 */
@Service
@Slf4j
public class IndexServiceImpl implements IndexService {

	@Resource
	private UserDao userDAO;
	@Resource
	private UserJwtDao userJwtDao;
	@Resource
	private LoginLogDao loginLogDao;
	@Resource
	private AuthManager authManager;
	@Resource
	private MenuDao menuDAO;
	@Resource
	private HttpServletRequest request;
	@Resource
	private TokenTemporaryCache tokenTemporaryCache;

	/**
	 * 登录
	 * @param request
	 * @param loginDto
	 * @return
	 */
	@Override
	@Transactional
	public ResultMessage login(HttpServletRequest request, LoginDto loginDto) {
		ResultMessage rm = new ResultMessage();
		UserInfo user = userDAO.getUserByAccount(loginDto.getAccount());
		if ( user == null )
			throw new YitunException(ExceptionEnum.USER_NOT_FOUND);
		String type=user.getType();
//		if(! UserRoleTypeEnums.TYPE_ROOT.getType().equals(type) && !UserRoleTypeEnums.TYPE_ADMIN.getType().equals(type))
//			throw new YitunException(ExceptionEnum.USER_ABANDON);
		if (!YitunMD5Util.md5L32(loginDto.getPassword()).equals(user.getPassword()))
			throw new YitunException(ExceptionEnum.USERNAME_OR_PASSWORD_ERROR);
		Long userId = user.getId();
		String ip = YitunHttpUtil.getIpAddr(request);
		user.setIp(ip);
		String token = authManager.createToken(UserDto2PoConverter.INSTANCE.do2dto(user));
		authManager.putToken(token, userId);
		if (UserRoleTypeEnums.TYPE_ROOT.getType().equals(type)) {// 如果是超级管理员，则拥有所有权限
			authManager.putAuth(token, userId);
		}
		updateToken(token, user);
		//插入登录记录
		insertLoginHistory(user , user.getId() , LoginStatusEnums.LOGIN.getCode());
		// client端目前需要用户信息回显
		if (YitunStringUtil.isNotEmpty(loginDto.getLoginType()) && LoginTypeEnums.CLIENT.getCode().equals(loginDto.getLoginType())) {
			rm.bodyPut("user", userDAO.getVO(user.getId()));
			tokenTemporaryCache.put(token, user.getId());
		}
		rm.bodyPut("token", token);

		return rm;
	}

	/**
	 * 登出
	 */
	@Override
	@Transactional
	public void apilogout(JwtUserDto jwtUserDto) {
		UserInfo currentUser = userDAO.get(jwtUserDto.getUserId());
		OnlineUserDto jwtUserPo = new OnlineUserDto();
		jwtUserPo.setIp(jwtUserDto.getIp());
		jwtUserPo.setUserId(jwtUserDto.getUserId());
		//更新user-token表
		jwtUserPo.setToken("");
		jwtUserPo.setStatus(BaseInfo.STATUS_ZERO);
		userJwtDao.updateJwt(jwtUserPo);
		//插入登录记录
		insertLoginHistory(currentUser , currentUser.getId() , LoginStatusEnums.LOGOUT.getCode());
		//删除token
		authManager.removeByToken(jwtUserDto.getToken());
	}

	/**
	 * 查询用户所有的菜单权限，并添加到当前权限map中
	 * @param userId
	 * @param token
	 * @return
	 */
	@Override
	public List<MenuVo> menuList(Long userId, String token) {
		// List<Menu> list =new ArrayList<Menu>();
		// User user = userDAO.get(userId);
		// if(null!=user){
		// if (user.getType() == User.type_system) {//如果是超级管理员，则拥有所有权限
		// list =menuDAO.getAllMenuList();
		// }else{
		// list =userMenuDAO.getMenuListByUserId(userId);
		// }
		// }
		List<MenuVo> list = menuDAO.getMenuListByUserId(userId);
		List<String> permsList = new ArrayList<>();
		for (MenuVo m : list) {
			if (!permsList.contains(m.getPerms())) {
				permsList.add(m.getPerms());
			}
		}
		authManager.setPerms(token, permsList);
		return list;
	}
	@Override
	public UserInfo getUser(Long id) {
		UserInfo user = userDAO.get(id);
		return user;
	}


	/**
	 * 保存登录日志
	 */
	@Transactional
	public void updateToken(String jwtToken , UserInfo user) {
		OnlineUserDto jwtUserPo = new OnlineUserDto();
		jwtUserPo.setIp( user.getIp() );
		jwtUserPo.setUserId(user.getId());
		// 生成token
		jwtUserPo.setToken(jwtToken);
		jwtUserPo.setStatus(BaseInfo.STATUS_NORMAL);
		if (userJwtDao.getUserJwt(user.getId()) == null ){
			userJwtDao.saveJwt(jwtUserPo);
		}else{
			userJwtDao.updateJwt(jwtUserPo);
		}
	}

	/**
	 * 添加登陆记录
	 *
	 * @param loginDto
	 */
	@Override
	public void insertLoginHistory(UserInfo loginDto , Long acceptId , String status) {
		LoginLogPo loginLogPO = new LoginLogPo();
//        String address = HttpUtil.getAddressByIp(HttpUtil.getIpAddr(request));
//        loginLogPO.setIp(address + "(" + HttpUtil.getIpAddr(request) + ")");
		loginLogPO.setIp( loginDto.getIp() );
//		if (loginDto.getIpAddr() != null)
//			loginLogPO.setIpAddr(loginDto.getIpAddr().getCountry() + loginDto.getIpAddr().getProvince() + loginDto.getIpAddr().getCity());
		loginLogPO.setOperatorId(loginDto.getId());
		if (acceptId != null )
			loginLogPO.setAcceptId(acceptId);
//        loginLogPO.setOperatorAccount(loginDto.getUsername());
//        loginLogPO.setOperatorNickName(loginDto.getNickName());

		//1 上线 0下线 -1强制下线
		loginLogPO.setOperatorType(status);
		if (LoginStatusEnums.LOGIN.getCode().equals(status)){
			loginLogPO.setRemark("进行登陆操作");
		}else if (LoginStatusEnums.LOGOUT.getCode().equals(status) ){
			loginLogPO.setRemark("进行登出操作");
		}else if (LoginStatusEnums.FORCE_LOGOUT.getCode().equals(status) ){
			loginLogPO.setRemark("进行强制登出操作");
		}
		loginLogDao.save(loginLogPO);
	}

	/**
	 * 强退用户
	 * @param userId
	 * @param jwtUserDto
	 */
	@Transactional
	@Override
	public void forceLogout(Long userId , JwtUserDto jwtUserDto) {
		if (jwtUserDto.getUserId() == userId)
			throw new YitunException(ExceptionEnum.CANT_FORCE_OUT_CURRENT_USER);
		if (userId == 1)
			return ;
		UserInfo targetUser = userDAO.get(userId);
		OnlineUserDto jwtUserPo = new OnlineUserDto();
		String remoteIp = YitunHttpUtil.getIpAddr(request);
		jwtUserPo.setIp(remoteIp);
		jwtUserPo.setUserId(targetUser.getId());
		// 生成token
		jwtUserPo.setToken("");
		jwtUserPo.setStatus(BaseInfo.STATUS_ZERO);
		userJwtDao.updateJwt(jwtUserPo);
		//插入登录记录
		try{
			insertLoginHistory(targetUser ,userId ,  LoginStatusEnums.FORCE_LOGOUT.getCode());
		}catch (Exception e){
			log.info("插入登录记录失败");
		}
		//删除用户缓存信息
		authManager.removeByToken(jwtUserDto.getToken());
	}


}
